package cs275.ants.agent;

import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import junit.framework.TestCase;

import org.easymock.EasyMock;

import com.google.common.collect.Sets;

import cs275.ants.graph.antgraph.AntGraphVertex;
import cs275.ants.graph.base.Graph;
import cs275.ants.graph.base.GraphEdge;
import cs275.ants.graph.base.GraphVertex;
import cs275.ants.testing.MockRandom;

public class AntTest extends TestCase {

	private Ant ant;
	
	private Graph graph;
	private GraphVertex currentPosition;
	private GraphVertex destination;
	private GraphVertex disconnectedDestination;

	private MockRandom mockRandom;
	
	@Override
	protected void setUp() {
		Logger.getLogger(Ant.class.getName()).setLevel(Level.FINEST);
		graph = EasyMock.createNiceMock(Graph.class);
		currentPosition = EasyMock.createNiceMock(GraphVertex.class);
		destination = EasyMock.createNiceMock(GraphVertex.class);
		disconnectedDestination = EasyMock.createNiceMock(GraphVertex.class);
		
		mockRandom = new MockRandom();
		ant = new Ant(graph, currentPosition, mockRandom);
	}

	public void testMove() {
		HashSet<GraphEdge> edges = Sets.<GraphEdge> newHashSet(new GraphEdge(
				currentPosition, destination, 2));

		expect(graph.getEdgesByVertex(currentPosition)).andStubReturn(edges);
		replay(graph, currentPosition, destination, disconnectedDestination);

		assertTrue(ant.move(destination));
		assertFalse(ant.move(disconnectedDestination));
		verify(graph, currentPosition, destination, disconnectedDestination);
	}
	
	public void testChooseNextMove_noEdges() {
		HashSet<GraphEdge> edges = Sets.<GraphEdge>newHashSet();
		expect(graph.getEdgesByVertex(currentPosition)).andStubReturn(edges);
		replay(graph, currentPosition, destination, disconnectedDestination);
		try {
			ant.chooseNextMove();
			fail("Should have failed without neighbors.");
		} catch (IllegalStateException e) {
			// pass
		}
	}
	
	public void testChooseNextMove() {
		GraphVertex vertex1 = EasyMock.createNiceMock(GraphVertex.class);
		GraphVertex vertex2 = EasyMock.createNiceMock(GraphVertex.class);
		GraphVertex vertex3 = EasyMock.createNiceMock(GraphVertex.class);
		
		expect(graph.getEdgesByVertex(vertex1)).andStubReturn(
				Sets.newHashSet(new GraphEdge(vertex1, currentPosition)));
		expect(graph.getEdgesByVertex(vertex2)).andStubReturn(
				Sets.newHashSet(new GraphEdge(vertex2, currentPosition)));
		expect(graph.getEdgesByVertex(vertex3)).andStubReturn(
				Sets.newHashSet(new GraphEdge(vertex3, currentPosition)));
		
		HashSet<GraphEdge> edges = Sets.<GraphEdge>newLinkedHashSet();
		edges.add(new GraphEdge(vertex1, currentPosition, 1));
		edges.add(new GraphEdge(currentPosition, vertex2, 3));
		edges.add(new GraphEdge(vertex3, currentPosition, 5));

		expect(graph.getEdgesByVertex(currentPosition)).andStubReturn(edges);
		replay(graph, currentPosition, vertex1, vertex2, vertex3);

		double totalCost = 1 * 3 * 5;
		
		mockRandom.seedNextDouble(0);
		assertEquals(vertex1, ant.chooseNextMove());

		mockRandom.seedNextDouble(2 / totalCost);
		assertEquals(vertex2, ant.chooseNextMove());
	}
	
	public void testVertexIsFood() {

		AntGraphVertex baseVertex = new AntGraphVertex(0,0);
		AntGraphVertex vertex1 = new AntGraphVertex(0,1);
		AntGraphVertex vertex2 = new AntGraphVertex(1,0);
		vertex1.setFood(true);
//		vertex2.setIsFood(false);
		
		Graph graph2 = new Graph();
		graph2.addVertex(baseVertex);
		
		graph2.addVertex(vertex1);
		GraphEdge edge1 = new GraphEdge(vertex1, baseVertex, 1);
		graph2.addEdge(edge1);
		HashSet<GraphVertex> vertices = graph2.getNeighborsByVertex(baseVertex);		
		Iterator<GraphVertex> iter = vertices.iterator();
		AntGraphVertex vertex11 = (AntGraphVertex) iter.next();
		assertTrue(vertex11.hasFood());
		graph2.removeEdge(edge1);
		
		graph2.addVertex(vertex2);
		GraphEdge edge2 = new GraphEdge(vertex2, baseVertex, 1);
		graph2.addEdge(edge2);
		vertices = graph2.getNeighborsByVertex(baseVertex);		
		iter = vertices.iterator();
		AntGraphVertex vertex21 = (AntGraphVertex) iter.next();
		assertFalse(vertex21.hasFood());
		graph2.removeEdge(edge2);

	}
}
